package com.example.downloaddemo.downloader;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;


public class DownloadService extends Service {

    private Map<Integer, DownloadTask> mDownloadTask = new HashMap<>();
    private ExecutorService executorService;
    private LinkedBlockingDeque<DownloadEntry> mWaitingQueue = new LinkedBlockingDeque<>();
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            DownloadEntry downloadEntry = (DownloadEntry) msg.obj;
            switch (downloadEntry.status) {
                case cancel:
                    checkNext(downloadEntry);
                    break;
                case completed:
                    checkNext(downloadEntry);
                    break;
                case pause:
                    break;
                case waiting:
                    break;
            }
            DataChanger.getInstance().postStatus((DownloadEntry) msg.obj);
        }
    };

    private void checkNext(DownloadEntry downloadEntry) {
        DownloadEntry poll = mWaitingQueue.poll();
        if (poll != null) {
            startDownload(poll);
        }
    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        executorService = Executors.newCachedThreadPool();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        DownloadEntry downloadEntry = (DownloadEntry) intent.getSerializableExtra(Constants.KEY_DOWNLOAD_ENTRY);
        int action = intent.getIntExtra(Constants.KEY_DOWNLOAD_ACTION, -1);
        doAction(action, downloadEntry);
        return super.onStartCommand(intent, flags, startId);
    }

    private void doAction(int action, DownloadEntry downloadEntry) {
        switch (action) {
            case Constants.KEY_DOWNLOAD_ACTION_ADD:
                addDownLoad(downloadEntry);
                break;
            case Constants.KEY_DOWNLOAD_ACTION_PAUSE:
                pauseDownload(downloadEntry);
                break;
            case Constants.KEY_DOWNLOAD_ACTION_RESUME:
                resumeDownload(downloadEntry);
                break;
            case Constants.KEY_DOWNLOAD_ACTION_CANCEL:
                cancelDownload(downloadEntry);
                break;
        }
    }

    private void addDownLoad(DownloadEntry downloadEntry) {
        Log.e("TAG","===========mDownloadTask====="+mDownloadTask.size());
        if (mDownloadTask.size() > Constants.MAX_DOWNLOAD_TASKS) {
            mWaitingQueue.offer(downloadEntry);
            downloadEntry.status = DownloadEntry.DownloadStatus.waiting;
            DataChanger.getInstance().postStatus(downloadEntry);
        } else {
            startDownload(downloadEntry);
        }
    }

    private void cancelDownload(DownloadEntry downloadEntry) {
        DownloadTask task = mDownloadTask.get(downloadEntry.getId());
        if (task != null){
            task.cancel();
            mDownloadTask.remove(downloadEntry.getId());
        }else {
            mWaitingQueue.remove(downloadEntry);
        }
    }

    private void resumeDownload(DownloadEntry downloadEntry) {

    }

    private void pauseDownload(DownloadEntry downloadEntry) {
        DownloadTask task = mDownloadTask.get(downloadEntry.getId());
        if (task != null){
            task.pause();
        }else {
            mWaitingQueue.remove(downloadEntry);
        }
    }

    private void startDownload(DownloadEntry downloadEntry) {
        DownloadTask task = new DownloadTask(downloadEntry, mHandler);
//        task.start();
        mDownloadTask.put(downloadEntry.getId(), task);
        executorService.execute(task);
    }
}
